#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <signal.h>
#include <mqueue.h>

#define MAXSIZE     10   //定义buf大小
#define BUFFER      8192 //定义Msg大小

struct MsgType{
    int len;
    char buf[MAXSIZE];
    char x;
    short y;
};
mqd_t msgq_id;	
void message_callback(int signum, siginfo_t* info, void* context);

int main(int argc, char **argv){

    struct sigevent se;
    struct sigaction sa;
	printf("\r\n");
    printf("(SERVER) My PID: %d\n\n", getpid());
    
    msgq_id = mq_open("/posix", O_RDWR | O_CREAT, 0777, NULL);
		
	for(;;)
	{
		se.sigev_notify = SIGEV_SIGNAL;
		se.sigev_signo = SIGUSR1;

		mq_notify(msgq_id, &se);
		
		sa.sa_flags = SA_SIGINFO;
		sa.sa_sigaction = &message_callback;
		
		sigemptyset(&(sa.sa_mask));
		if(sigaction(SIGUSR1, &sa, NULL) == -1){
			perror("sigaction");
			exit(1);
		}
		pause();
	}

    mq_close(msgq_id);
    
    return 0;
}

void message_callback(int signum, siginfo_t* info, void* context){
	struct MsgType msg;
    unsigned int sender;
    unsigned int recv_size = BUFFER;
	
    if(signum == SIGUSR1){
        if(info->si_code == SI_MESGQ){
			msg.len = -1;
			memset(msg.buf, 0, MAXSIZE);
			msg.x = ' ';
			msg.y = -1;	
			
            printf("Message received from PID %d:\n", info->si_pid);
			/* getting a message */
			/*mq_receive() 从由描述符 mqdes 引用的队列时删除优先级最高的最老的消息，并把放置到 msg_ptr 的缓存区内。*/
			/*参数 msg_len 指定缓冲区 msg_ptr 的大小：它必须大于队列的 mq_msgsize 属性(参数 mq_getattr)。*/ 
			/*如果 prio 不是 NULL，那么它指向的内存用于返回收到消息相关的优先级。*/
			if (mq_receive(msgq_id, (char*)&msg, recv_size, &sender) == -1) 
			{
				perror("mq_receive");
				exit(1);
			}
			printf("msg.len = %d, msg.buf = %s, msg.x = %c, msg.y = %d\n", msg.len, msg.buf, msg.x, msg.y);
        }
    } 
}